﻿package tbo.world 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import tbo.events.TBOActorEvent;
	import tbo.game.BattleManager;
	import tbo.world.TacticalGrid;
	import tbo.model.Application;
	import tbo.model.Player;
	import tbo.actors.Actor;
	
	/**
	 * The vible stage that is displayed to the user
	 * @author ...
	 */
	public class TacticalStage extends Sprite
	{
		
		protected var _actors:Array;
		protected var _grid:TacticalGrid;
		
		protected var _scale:Number = 40;
		
		protected var gridSp:Sprite;
		protected var actorSp:Sprite;
		protected var overSp:Sprite;
		
		protected var bManager:BattleManager;
		
		public function TacticalStage(manager:BattleManager) 
		{
			bManager = manager;
			_grid = new TacticalGrid(10, 10);
			
			gridSp = new Sprite();
			this.addChild(gridSp);
			
			overSp = new Sprite();
			this.addChild(overSp);
			
			//_scale = Application.scale;
			
			actorSp = new Sprite();
			_actors = new Array();
			this.addChild(actorSp);
			for (var i:String in Player.units) {
				actorSp.addChild(Player.units[i]);
				Player.units[i].addEventListener(Actor.END_MOVE, onActorMove);
				Player.units[i].addEventListener(TBOActorEvent.TARGET_START, beginTarget);
				Player.units[i].addEventListener(TBOActorEvent.MOVE_START, beginMove);
				Player.units[i].addEventListener(MouseEvent.CLICK, onActorClicked);
				_actors.push(Player.units[i]);
			}
			
			drawGrid();
			
			this.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
			this.addEventListener(MouseEvent.CLICK, onMclick);
		}
		
		public function onMclick(e:MouseEvent):void {
			clearOverSp();
		}
		
		public function onMove(e:MouseEvent):void {
			
		}
		
		public function onActorClicked(e:MouseEvent):void {
			bManager.handleActorClick(Actor(e.target));
		}
		
		public function onActorMove(e:Event):void {
			
			var stageX:Number = Math.floor(e.target.x / _scale);
			var stageY:Number = Math.floor(e.target.y / _scale);
			
			if (_grid.isWalkable(stageX, stageY) && Actor(e.target).withinWalkingRange(stageX, stageY)) {
				e.target.x = stageX * _scale;
				e.target.y = stageY * _scale;
				e.target._wx =  stageX;
				e.target._wy = stageY;
				_grid.setUnit(Actor(e.target));
			} else {
				e.target.x = e.target._wx * _scale;
				e.target.y = e.target._wy * _scale;
			}
			
			
			
			clearOverSp();
			//bManager.setState("wait");
			//dispatchEvent(new TBOActorEvent(TBOActorEvent.ACTOR_CLICKED, Actor(e.target)));
		}
		
		public function beginTarget(e:TBOActorEvent):void {
			bManager.setState("target");
			drawRange(e.actor._wx, e.actor._wy, e.actor._attacks[0].range);
		}
		
		public function beginMove(e:TBOActorEvent):void {
			bManager.setState("move");
			drawRange(e.actor._wx, e.actor._wy, e.actor.range);
		}
		
		public function drawGrid():void {
			for (var x:Number = 0; x < _grid.length; x++) {
				for ( var y:Number = 0; y < _grid.height; y++) {
					var shape:Sprite = new Sprite();
					shape.graphics.lineStyle(1, 0x000000);
					if (!_grid.getGridData(x, y).walkable) {
						shape.graphics.beginFill(0x000000);
					}
					shape.graphics.drawRect(0, 0, _scale, _scale);
					shape.x = _scale * x;
					shape.y = _scale * y;
					gridSp.addChild(shape);
				}
			}
		}
		
		public function clearOverSp():void {
			while(overSp.numChildren) {
				overSp.removeChildAt(0);
			}
		}
		
		public function drawRange(cx:Number, cy:Number, r:Number):void {
			clearOverSp();
			var shape:Sprite;
			for (var ix:Number = -r; ix <= r; ix ++) {
				for (var iy:Number = -r; iy <= r; iy++) {
					if ((Math.abs(ix) + Math.abs(iy) <= r) && _grid.isWalkable(cx + ix, cy + iy) ) {
						shape = new Sprite();
						shape.x = (cx + ix) * _scale;
						shape.y = (cy + iy) * _scale;
						shape.graphics.beginFill(0xFF0000, .5);
						shape.graphics.drawRect(0, 0, _scale, _scale);
						shape.graphics.endFill();
						overSp.addChild(shape);
					}

				}
			}
		}
		
		public function get units():Array {
			return _actors;
		}
		
		public function get grid():TacticalGrid {
			return _grid;
		}
		
	}
	
}